//
// Created by dongbo on 11/12/18.
//

#ifndef PAXOS_PNODE_H
#define PAXOS_PNODE_H

#include <iostream>
#include "role_node.h"

class pclient {
public:
    struct client {
        int id;
        struct timeval tv;
        int write_pipefd;
        struct event_base *base;
        struct bufferevent *bev;
        struct bufferevent *bev0;
        struct event *timer;   /* Timer to connect to proposer */
        struct event *stats_ev;
        struct event *sig;
        struct evlearner *learner;
    };
    struct msg {
        int id;
        std::string str;
    };

public:
    pclient(int _appid_id, struct evpaxos_config *_config) : appid(_appid_id), config(_config), ok(false) {}

    void make_client(int id);

    void client_free();

    void start_client();

    int SendMsg(std::string msg, int id = 0);

    bool is_ok() { return ok; }

private:
    static void client_submit_value(struct client *c, std::string str_msg);

    static void on_connect(struct bufferevent *bev, short events, void *arg);

    static void on_pipe_read(struct bufferevent *bev, void *arg);

    static void on_connection_err(int fd, short ev, void *arg);

    static void connect_to_proposer(struct pclient *c, int proposer_id, struct evpaxos_config *conf);

private:
    std::atomic_bool ok;
    int appid;
    client *c;
    struct evpaxos_config *config;
};


class pnode {

public:
    pnode(int _id, struct evpaxos_config *_config, zmqpipe *_zpip = nullptr, ppax_cb *ppxcb = nullptr);

    int init_pnode();

    int proposer_connect_new_acceptor(int id, struct sockaddr_in);

    int leaner_connect_new_acceptor(int id, struct sockaddr_in);

    void set_zpip(zmqpipe *_zpip, int zip_num);

public:
    pclient *client_node;
    role_proposer *proposer;
    role_acceptor *acceptor;
    role_learner *learner;

    int num_pxnode;
private:
    int id;
    struct evpaxos_config *config;
};


#endif //PAXOS_PNODE_H
